home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / d_d / caltech / inbound / mcm / mcm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-22  |  44.0 KB  |  1,981 lines

  1. /* MCM  -  MultiUser Communications Manager
  2.  
  3.    Copyright (C) 1991,2 Michael Sawyer
  4.  
  5.    This code may be reproduced without charge provided that this
  6.    notice remains intact on all copies distributed.
  7.  
  8.    Any part of this code may be used in other programs provided that
  9.    some citation of this work is given.
  10. */
  11.  
  12. #include "mcm.h"
  13.  
  14. #ifndef    lint
  15. static char mcm_sourceid[] =
  16.     "@(#)mcm.c,v 1.2 1992/08/18 00:40:00 msawyer";
  17. #endif
  18.  
  19. #ifdef NEED_USLEEP
  20. /*-
  21.  * usleep.c - OS dependant implementation of usleep().
  22.  *
  23.  * Copyright (c) 1991 by Patrick J. Naughton.
  24.  *
  25.  * Revision History:
  26.  * 30-Aug-90: written.
  27.  *
  28.  */
  29.  
  30. #include <sys/types.h>
  31. #include <sys/time.h>
  32.  
  33. #ifndef    lint
  34. static char sleep_sourceid[] =
  35.     "@(#)usleep.c,v 1.4 1992/06/28 05:38:33 bjoerns Exp";
  36. #endif
  37.  
  38.  
  39. int
  40. usleep(usec)
  41.     unsigned long usec;
  42. {
  43. /*#ifdef SYSV
  44.     poll((struct poll *) 0, (size_t) 0, usec / 1000);    /* ms RES */
  45. /*#else*/
  46.     struct timeval timeout;
  47.     timeout.tv_usec = usec % (unsigned long) 1000000;
  48.     timeout.tv_sec = usec / (unsigned long) 1000000;
  49.     (void) select(0, (void *) 0, (void *) 0, (void *) 0, &timeout);
  50. /*#endif*/
  51.     return 0;
  52. }
  53. #endif
  54.  
  55. void bailout(exitcode, message)
  56. int exitcode;
  57. char message[];
  58. {
  59.   int i;
  60.   char *textptr;
  61.   char output[256];
  62.  
  63.   switch (exitcode)
  64.   {
  65.   case 1:
  66.   case 2:
  67.     sprintf (output,"(sys) SERVER FAILED SANITY CHECK: %s\r\n",message);
  68.     perror (message);
  69.     break;
  70.   case 0:
  71.     sprintf (output,"(sys) SERVER SHUTDOWN: %s\r\n",message);
  72.     break;
  73.   case 3:
  74.     sprintf (output,"(sys) SERVER FAILURE: %s\r\n",message);
  75.     break;
  76.   default:
  77.     strcpy (output,"(sys) UNKNOWN SERVER FAILURE --- Shutting down\r\n");
  78.   }
  79.   fputs (output,stderr);
  80.   fputs (output,logfp);
  81.   fputs (output,masterfp);
  82.   fclose (masterfp);
  83.   for (i=0;i<NUMJOBS;i++)
  84.     if (job[i].fd!=0)
  85.     {
  86.       write (job[i].fd,output,strlen(output));
  87.       close (job[i].fd);
  88.     }
  89.   if (s!=0)
  90.   {
  91.     close (s);
  92.   }
  93.   exit (exitcode);
  94. }
  95.  
  96. void sigprocessor(sig)
  97. int sig;
  98. {
  99.   char string[256];
  100.   FILE *fp;
  101.   int i;
  102.  
  103.   switch (sig)
  104.   {
  105.   case SIGUSR1:
  106.     sprintf (string,"/tmp/%d-message",portid);
  107.     if ((fp=fopen(string,"r"))==NULL)
  108.       return; /* There is no message there */
  109.     fgets (string,80,fp);
  110.     fclose (fp);
  111.     string[strlen(string)-1]=0;
  112.     tell (-1,-1,"(sys)",string);
  113.     sprintf (string,"rm /tmp/%d-message",portid);
  114.     system (string);
  115.     signal (SIGUSR1,sigprocessor);
  116.     return;
  117.   case SIGTERM:
  118.   case SIGINT:
  119.   case SIGQUIT:
  120.   case SIGABRT:
  121.     bailout (0,"Shutdown from system operator");
  122.   case SIGILL:
  123.     bailout (3,"Illegal Instruction Trap");
  124.   case SIGEMT:
  125.     bailout (3,"Emulator Trap");
  126.   case SIGFPE:
  127.     bailout (3,"Floating Point Trap");
  128.   case SIGBUS:
  129.     bailout (3,"Bus Error Trap");
  130.   case SIGSEGV:
  131.     bailout (3,"Segment Violation Trap");
  132.   case SIGSYS:
  133.     bailout (3,"System Trap");
  134.   default:
  135.     bailout (3,"Unknown system fault");
  136.   }
  137. }
  138.  
  139. int testjob(jobid)
  140. int jobid;
  141. {
  142.   if ((jobid<0)||(jobid>NUMJOBS))
  143.     return FALSE;
  144.   if (job[jobid].mode!=3)
  145.     return FALSE;
  146.   return TRUE;
  147. }
  148.  
  149. int main(argc,argv)
  150. int argc;
  151. char **argv;
  152. {
  153.   int i; 
  154.   long g;
  155.   time_t tm, last_tm;
  156.   char string[80];
  157.  
  158.   msgtext[0]=0;
  159.   s=0;
  160.   signal (SIGUSR1,sigprocessor);
  161.   signal (SIGUSR2,per_sig2);
  162.   signal (SIGHUP,SIG_IGN);
  163.   signal (SIGINT,sigprocessor);
  164.   signal (SIGQUIT,sigprocessor);
  165.   signal (SIGILL,sigprocessor);
  166.   signal (SIGABRT,sigprocessor);
  167.   signal (SIGEMT,sigprocessor);
  168.   signal (SIGFPE,sigprocessor);
  169.   signal (SIGBUS,sigprocessor);
  170.   signal (SIGSEGV,sigprocessor);
  171.   signal (SIGSYS,sigprocessor);
  172.   signal (SIGPIPE,SIG_IGN);
  173.   signal (SIGALRM,SIG_IGN);
  174.   signal (SIGTERM,sigprocessor);
  175.   signal (SIGURG,SIG_IGN);
  176.  
  177.   listen_mode= -1;
  178.   snoopmode=FALSE;
  179.   confhear=TRUE;
  180.   conftalk=TRUE;
  181.   whogagged=1;
  182.   asstleader=0;
  183.   masterfp=NULL;
  184.   msgcount=0;
  185.   for (i=0;i<NUMJOBS;i++)
  186.   {
  187.     job[i].buf[0]=0;
  188.     job[i].name[0]=0;
  189.     job[i].from[0]=0;
  190.     job[i].mode=0;
  191.     job[i].gagged=0;
  192.     job[i].privconf=0;
  193.     job[i].maybeleader=0;
  194. #ifdef TERMCAP
  195.     job[i].termtype[0]=0;
  196. #endif
  197.   }
  198.  
  199.   if (argc!=2)
  200.   {
  201.     fputs ("Usage: mcm portid\r\n",stderr);
  202.     exit (1);
  203.   }
  204.   portid=atoi(argv[1]);
  205.   if ((masterfp=fopen("master-log","w"))==NULL)
  206.   {
  207.     perror ("master-log");
  208.     bailout(2,"open master-log");
  209.   }
  210.   if ((logfp=fopen("mcm-log","w"))==NULL)
  211.   {
  212.     perror ("mcm-log");
  213.     bailout(2,"open mcm-log");
  214.   }
  215.   time(&last_tm);
  216.   fprintf (logfp,"(sys) Startup on port %d at %s",portid,ctime(&last_tm));
  217.   fprintf (masterfp,"(sys) Startup on port %d at %s",portid,ctime(&last_tm));
  218.   sin.sin_family=AF_INET;
  219.   sin.sin_addr.s_addr=htonl(INADDR_ANY);
  220.   sin.sin_port=htons(portid);
  221.   if ((s=socket(AF_INET,SOCK_STREAM,0))<0)
  222.     bailout (2,"mcm socket");
  223.   i=1;
  224.   setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
  225.   if (bind(s, (struct sockaddr_in *)&sin,sizeof (struct sockaddr_in))<0)
  226.     bailout (2,"mcm bind");
  227.   listen (s,5);
  228.  
  229.   i=1; /* We are going to turn on non-blocking IO */
  230.   if (ioctl(s,FIONBIO,&i)<0)
  231.     bailout (2,"mcm ioctl_nbio");
  232.   if (ioctl(s,FIOASYNC,&i)<0)
  233.     bailout (2,"mcm ioctl_async");
  234.   i=0;
  235.  
  236.   setpriority (PRIO_PROCESS,getpid(),HOWNICE); /* Make this nice */
  237.   srand48 (getpid());
  238.  
  239.   per_init();
  240.  
  241. #ifdef DELTAT
  242.   last_tm=(last_tm/DELTAT)*DELTAT;
  243. #endif
  244.   while (TRUE)
  245.   {
  246. #ifdef DELTAT
  247.     time(&tm);
  248.     if (tm-last_tm>=DELTAT)
  249.     {
  250.       sprintf (string,"%s",ctime(&tm));
  251.       tell (-1,-1,"(time)",string);
  252.       last_tm=(tm/DELTAT)*DELTAT;
  253.     }
  254. #endif
  255.     check_connections(); /* Check for new connections */
  256.     if (communicate()==FALSE)
  257.     {
  258.       usleep (DELAYTIME);
  259.       fflush (logfp);
  260.       fflush (masterfp);
  261.     }
  262.     per_timestep();
  263.   }
  264. }
  265.  
  266. void check_connections()
  267. {
  268.   int newfd;
  269.   int i;
  270.   char string[256];
  271.   char *name;
  272.  
  273.   i=sizeof(sin);
  274.   newfd=accept(s,(struct sockaddr *)&sin,&i);
  275.   if (newfd<0)
  276.     return; /* Nothing there... */
  277.   setsockopt(s,SOL_SOCKET,SO_LINGER,&i,sizeof(int));
  278.   for (i=1;i<NUMJOBS;i++)
  279.   {
  280.     if (job[i].fd==0)
  281.     {
  282.       job[i].fd=newfd;
  283. #ifdef TERMCAP
  284.       job[i].termtype[0]=0;
  285. #endif
  286.       job[i].addrs[0]=sin.sin_addr.S_un.S_un_b.s_b1;
  287.       job[i].addrs[1]=sin.sin_addr.S_un.S_un_b.s_b2;
  288.       job[i].addrs[2]=sin.sin_addr.S_un.S_un_b.s_b3;
  289.       job[i].addrs[3]=sin.sin_addr.S_un.S_un_b.s_b4;
  290.       job[i].firstrun=TRUE;
  291.       job[i].buf[0]=0;
  292.       /* Set line-at-a-time mode */
  293.       write (job[i].fd,"\377\374\001\377\374\003",6);
  294.       sprintf (string,"Connection established on port %d job id %d",
  295.            portid, i);
  296.       tell (-1,i,"(sys)",string);
  297.       if (!access("mcm-welcome",R_OK))
  298.     usertype (i,"mcm-welcome");
  299.       tell (-1,i,"","Enter your name:");
  300.       job[i].mode=1;
  301.       return;
  302.     }
  303.   }
  304.   write (newfd,"Sorry, job limit has been reached.\r\n",35);
  305.   close (newfd);
  306. }
  307.  
  308. int communicate()
  309. {
  310.   int anyhits;
  311.   int i;
  312.   int j;
  313.   int len;
  314.   char inbuf[255];
  315.   char outbuf[512];
  316.   char *textptr;
  317.  
  318.   anyhits=FALSE;
  319.   for (i=0;i<NUMJOBS;i++)
  320.   {
  321.     if (job[i].fd!=0)
  322.     {
  323.       errno=0;
  324.       if ((len=read(job[i].fd,inbuf,255))<=0)
  325.       {
  326.     if (errno!=EWOULDBLOCK)
  327.     {
  328.       if (testjob(i))
  329.         tell (i,-1,"(sys)","DISCONNECTED");
  330.       job[i].mode=0;
  331.       endsession (i);
  332.     }
  333.       }
  334.       else /* we got some data */
  335.       {
  336.     anyhits=TRUE;
  337.     for (j=0;j<len;j++)
  338.     {
  339.       if (isprint(inbuf[j]))
  340.       {
  341.         if (strlen(job[i].buf)<250)
  342.         {
  343.           job[i].buf[strlen(job[i].buf)+1]=0;
  344.           job[i].buf[strlen(job[i].buf)]=inbuf[j];
  345. #ifdef TERMCAP
  346.           if (job[i].termtype[0]!=0)
  347.         splchar (i,inbuf[j]);
  348. #endif
  349.         }
  350.       }
  351.       else if (inbuf[j]=='\377')
  352.       {
  353.         j++;
  354.         if (j>='\373')
  355.           j++;
  356.       }
  357.       else if ((inbuf[j]=='\b')||(inbuf[j]=='\177'))
  358.       {
  359.         if (strlen(job[i].buf)>0)
  360.         {
  361.           job[i].buf[strlen(job[i].buf)-1]=0; /* Backspace */
  362. #ifdef TERMCAP
  363.           if (job[i].termtype[0]!=0)
  364.         splbackup (i);
  365. #endif
  366.         }
  367.       }
  368.       else if (inbuf[j]=='\014')
  369.       {
  370. #ifdef TERMCAP
  371.         if (job[i].termtype[0]!=0)
  372.           splredraw(i);
  373. #endif
  374.       }
  375.       else if ((inbuf[j]=='\025')||(inbuf[j]=='\030'))
  376.       {
  377.         job[i].buf[0]=0;
  378. #ifdef TERMCAP
  379.         if (job[i].termtype[0]!=0)
  380.         {
  381.           splnewinp(i);
  382.         }
  383. #endif
  384.       }
  385.       else if (inbuf[j]=='\027')
  386.       {
  387.         if ((textptr=strrchr(job[i].buf,' '))!=NULL)
  388.         {
  389.           textptr[0]=0;
  390. #ifdef TERMCAP
  391.           if (job[i].termtype[0]!=0)
  392.         splredraw(i);
  393. #endif
  394.         }
  395.       }
  396.       else if ((inbuf[j]=='\r')||
  397.            ((inbuf[j]=='\n')&&(inbuf[j+1]!='\r')&&(inbuf[j-1]!='\r')))
  398.       {
  399.         process (i,job[i].buf);
  400.         job[i].buf[0]=0;
  401. #ifdef TERMCAP
  402.         if (job[i].termtype[0]!=0)
  403.         {
  404.           splnewinp(i);
  405.         }
  406. #endif
  407.       }
  408.     }
  409.       }
  410.     }
  411.   }
  412.   return (anyhits);
  413. }
  414.  
  415. /* Word wrap a string.*/
  416. void wwrap(string)
  417. char *string;
  418. {
  419.   char newstring[512];
  420.   char *stpos, *stsow, *steow, *nspos, *nssol;
  421.   int len=80;
  422.  
  423.   if (strchr(string,'\n')!=NULL)
  424.     return; /* Already wrapped */
  425.   nssol=newstring;
  426.   nspos=newstring;
  427.   newstring[0]=0;
  428.   stpos=string;
  429.   stsow=string;
  430.   for (;;)
  431.   {
  432.     if ((steow=strchr(stpos,' '))==NULL)
  433.     {
  434.       if (strlen(nssol)+strlen(stpos)>len-5)
  435.       {
  436.     *nspos++='\r';
  437.     *nspos++='\n';
  438.     nssol=nspos;
  439.       }
  440.       for (;stpos[0]!=0;stpos++)
  441.     *nspos++= *stpos;
  442.       *nspos=0;
  443.       sprintf (string,"%s\r\n",newstring);
  444.       return;
  445.     }
  446.     *steow=0;
  447.     if (strlen(nssol)+strlen(stpos)>len-5)
  448.     {
  449.       *nspos++='\r';
  450.       *nspos++='\n';
  451.       nssol=nspos;
  452.     }
  453.     for (;stpos<steow;stpos++)
  454.       *nspos++= *stpos;
  455.     *nspos++=' ';
  456.     *nspos=0;
  457.     stpos++;
  458.   }
  459. }
  460.  
  461. /* New tell routines */
  462.  
  463. void txout(msgfrom, msgto, system, text, privmsg)
  464. int msgfrom, msgto, privmsg;
  465. char *system, *text;
  466. {
  467.   int i;
  468.  
  469.   /* -1 means 0 and ass't leader (Yeah, I know its ugly to have txout */
  470.   /* to -1 mean something different from tell -1...  Sorry. */
  471.   if (msgto== -1)
  472.     i=0;
  473.   else
  474.     i=msgto;
  475.   if (!validjob(i))
  476.   {
  477.     return;
  478.   }
  479.  
  480. #ifdef TERMCAP
  481.   if (job[i].termtype[0]!=0)
  482.     spltext(msgfrom, i, system, text, privmsg);
  483.   else
  484. #endif
  485.     easytext(msgfrom, i, system, text, privmsg);
  486.   if ((msgto== -1)&&(asstleader!=0)&&(msgfrom>=0)&&(msgfrom!=asstleader))
  487.     txout (msgfrom,asstleader,system,text,privmsg);
  488. }
  489.  
  490. void tell(msgfrom, msgto, system, text)
  491. int msgfrom, msgto;
  492. char *system, *text;
  493. {
  494.   char string[512];
  495.   char newsys[80];
  496.   int i;
  497.  
  498.   if (!per_tell(msgfrom,msgto,system,text))
  499.     return;
  500.   /* First deal with private messages... */
  501.   if (msgto>=0)
  502.   {
  503.     if (msgfrom<0) /* Its a system message; he can get it */
  504.     {
  505.       txout (msgfrom,msgto,system,text,TRUE);
  506.     }
  507.     else /* Its from someone */
  508.     {
  509.       /* Make sure that the jobs are valid */
  510.       if (!testjob(msgfrom))
  511.     return;
  512.       if (!testjob(msgto))
  513.       {
  514.     txout(-1,msgfrom,"(sys)","Attempt to send to invalid job.",TRUE);
  515.     return;
  516.       }
  517.  
  518.       /* First, check that if the rec. is on co, he can hear */
  519.       if ((!confhear)&&(job[msgto].privconf)&&(msgto!=0)
  520.       &&(msgto!=asstleader)&&(msgfrom!=0)&&(msgfrom!=asstleader))
  521.       {
  522.     txout (-1,msgfrom,"(sys)","Users in conference cannot be contacted."
  523.            ,TRUE);
  524.     return;
  525.       }
  526.  
  527.       /* And check the sender also */
  528.       if ((!conftalk)&&(job[msgfrom].privconf)&&(msgfrom!=0)
  529.       &&(msgfrom!=asstleader)&&(msgto!=0)&&(msgto!=asstleader))
  530.       {
  531.     txout (-1,msgfrom,"(sys)",
  532.           "You cannot send to users outside of conference.", TRUE);
  533.     return;
  534.       }
  535.  
  536.       /* Check gagging */
  537.       if ((job[msgfrom].gagged)&&(msgto!=0)&&(msgto!=asstleader))
  538.       {
  539.     txout (-1,msgfrom,"(sys)","You are gagged.",TRUE);
  540.     return;
  541.       }
  542.  
  543.       /* Check for deaf users */
  544. /*      if ((job[msgto].deaf)&&(msgfrom!=0)&&(msgfrom!=asstleader))
  545. *      {
  546. *    txout (-1,msgfrom,"(sys)","That user cannot hear you.",TRUE);
  547. *    return;
  548. *      }
  549. */
  550.  
  551.       /* OK, so now we can send the message */
  552.       sprintf (newsys,"(private)%s",system);
  553.       txout (msgfrom,msgto,newsys,text,TRUE);
  554.       if (snoopmode)
  555.       {
  556.     sprintf (string,"%d-%s: %s",msgto,job[msgto].name,text);
  557.     txout (msgfrom,-1,newsys,string,TRUE);
  558.     sprintf (string,"%s %d-%s> %d-%s: %s",newsys,msgfrom,
  559.          job[msgfrom].name,msgto,job[msgto].name,text);
  560.     wwrap (string);
  561.     fputs (string,masterfp);
  562.     return;
  563.       }
  564.     }
  565.   }
  566.   else /* Dealing with a public message; not as easy! */
  567.   {
  568.     msgcount++;
  569.     if (msgfrom < 0) /* System global message */
  570.     {
  571.       sprintf (string," %s %s",system,text);
  572.       wwrap (string);
  573.       fputs (string,logfp);
  574.       fputs (string,masterfp);
  575.       for (i=0;i<NUMJOBS;i++)
  576.       {
  577.     if (testjob(i))
  578.       tell (-1,i,system,text);
  579.       }
  580.       return;
  581.     }
  582.  
  583.     if (!testjob(msgfrom))
  584.       return;
  585.       
  586.     /* Need to resolve msgto -3 first (All or me and operator) */
  587.     if (msgto== -3)
  588.     {
  589.       if (  ((listen_mode!= -1)&&(listen_mode!=msgfrom)&&(msgfrom!=0))
  590.       || (job[msgfrom].gagged))
  591.       {
  592.     sprintf (newsys,"(private)%s",system);
  593.     txout (msgfrom,msgfrom,newsys,text,FALSE);
  594.     txout (msgfrom,-1,newsys,text,FALSE);
  595.     return;
  596.       }
  597.       msgto= -1;
  598.     }
  599.     
  600.     /* Now resolve -1 (all) */
  601.     if (msgto== -1)
  602.     {
  603.       if (msgfrom>=0)
  604.     msgto=job[msgfrom].privconf?-10:-2;
  605.       else
  606.     msgto= -2;
  607.     }
  608.     
  609.     /* -2 (Public all) */
  610.     if (msgto== -2)
  611.     {
  612.       if (job[msgfrom].gagged)
  613.       {
  614.     txout (-1,msgfrom,"(sys)",
  615.            "You are gagged; only room coord. will see your message",TRUE);
  616.     sprintf (newsys,"(gag)%s",system);
  617.     txout (msgfrom,-1,newsys,text,TRUE);
  618.     sprintf (string,"%s %d-%s> %s",newsys,msgfrom,
  619.          job[msgfrom].name,text);
  620.     wwrap (string);
  621.     fputs (string,masterfp);
  622.     return;
  623.       }
  624.       if ((job[msgfrom].privconf)&&(!conftalk)&&(msgfrom!=0)
  625.       &&(msgfrom!=asstleader))
  626.       {
  627.     txout (-1,msgfrom,"(sys)",
  628.            "Cannot send messages out of conference now.",TRUE);
  629.     return;
  630.       }
  631.       if ((listen_mode!= -1)&&(msgfrom!=listen_mode)&&(msgfrom!=0))
  632.       {
  633.     txout (-1,msgfrom,"(sys)",
  634.            "Room listen-only; only room coord. will see your message"
  635.            ,TRUE);
  636.     sprintf (newsys,"(lisn)%s",system);
  637.     txout (msgfrom,-1,newsys,text,TRUE);
  638.     sprintf (string,"%s %d-%s> %s",newsys,msgfrom,
  639.          job[msgfrom].name,text);
  640.     wwrap (string);
  641.     fputs (string,masterfp);
  642.     return;
  643.       }
  644.       for (i=0;i<NUMJOBS;i++)
  645.       {
  646.     if (testjob(i))
  647.     {
  648.       if ((confhear)||(!job[i].privconf)||(i==0)||(i==asstleader))
  649.         txout (msgfrom,i,system,text,FALSE);
  650.     }
  651.       }
  652.       sprintf (string,"%s %d-%s> %s",system,msgfrom,
  653.            job[msgfrom].name,text);
  654.       wwrap (string);
  655.       fputs (string,masterfp);
  656.       fputs (string,logfp);
  657.       return;
  658.     }
  659.     
  660.     /* -10 (All in conf) */
  661.     if (msgto== -10)
  662.     {
  663.       if ((!job[msgfrom].privconf)&&(msgfrom!=0))
  664.     /* Should never get here! */
  665.     return;
  666.       if ((job[msgfrom].gagged)&&(msgfrom!=0))
  667.       {
  668.     txout (-1,msgfrom,"(sys)",
  669.            "You are gagged; only room coord. will see your message",TRUE);
  670.     sprintf (newsys,"(gag)%s",system);
  671.     txout (msgfrom,-1,newsys,text,TRUE);
  672.     sprintf (string,"%s %d-%s> %s",newsys,msgfrom,
  673.          job[msgfrom].name,text);
  674.     wwrap (string);
  675.     fputs (string,masterfp);
  676.     return;
  677.       }
  678.       sprintf (newsys,"(conf)%s",system);
  679.       for (i=0;i<NUMJOBS;i++)
  680.       {
  681.     if (testjob(i))
  682.     {
  683.       if ((job[i].privconf)||(i==0)||(i==asstleader))
  684.         txout (msgfrom,i,newsys,text,FALSE);
  685.     }
  686.       }
  687.       sprintf (string,"%s %d-%s> %s",newsys,msgfrom,
  688.            job[msgfrom].name,text);
  689.       wwrap (string);
  690.       fputs (string,masterfp);
  691.       return;
  692.     }
  693.   }
  694. }
  695.  
  696.  
  697. void easytext(msgfrom, msgto, system, text, privmsg)
  698. int msgfrom, msgto, privmsg;
  699. char *system, *text;
  700. {
  701.   char outbuf[512];
  702.   char tempstring[64];
  703.  
  704.   if (msgfrom>=0)
  705.   {
  706.     outbuf[0]=0;
  707.     if (msgcount>99)
  708.       msgcount=0;
  709.     if ((job[msgto].showcount)&&(!privmsg))
  710.       sprintf (outbuf,"[%02d]",msgcount);
  711.     strcat (outbuf,system);
  712.     if (job[msgto].showjob)
  713.     {
  714.       sprintf (tempstring,"%d-",msgfrom);
  715.       strcat (outbuf,tempstring);
  716.     }
  717.     if (!job[msgto].padname)
  718.       strcat (outbuf,job[msgfrom].name);
  719.     else
  720.     {
  721.       sprintf (tempstring,"%-10s",job[msgfrom].name);
  722.       strcat (outbuf,tempstring);
  723.     }
  724.     strcat (outbuf,"> ");
  725.     strcat (outbuf,text);
  726.   }
  727.   else
  728.     sprintf (outbuf,"%s %s",system,text);
  729.   wwrap (outbuf);
  730.   write (job[msgto].fd,outbuf,strlen(outbuf));
  731. }
  732.  
  733. void process(msgfrom, command)
  734. int msgfrom;
  735. char *command;
  736. {
  737.   int msgto;
  738.   int i;
  739.   char system[40];
  740.   char outtext[256];
  741.   char *textptr;
  742.  
  743.   if (!validjob(msgfrom))
  744.     return;
  745.  
  746.   if (job[msgfrom].firstrun)
  747.   {
  748.     fprintf (masterfp,"(sys) CONNECT: job %d from %d.%d.%d.%d\n"
  749.          ,msgfrom,(int)job[msgfrom].addrs[0],(int)job[msgfrom].addrs[1]
  750.          ,(int)job[msgfrom].addrs[2],(int)job[msgfrom].addrs[3]);
  751.     job[msgfrom].firstrun=FALSE;
  752.   }
  753.  
  754.   if (job[msgfrom].mode==1)
  755.   {
  756.     strncpy (job[msgfrom].name,command,19);
  757.     loginuser(msgfrom);
  758.     return;
  759.   }
  760.   if (job[msgfrom].mode==2)
  761.   {
  762.     strncpy (job[msgfrom].pass,command,19);
  763.     loginuser(msgfrom);
  764.     return;
  765.   }
  766.  
  767.   if (strcmp("*+",command)==0) /* For someone to become a leader */
  768.   {
  769.     if (job[msgfrom].maybeleader==0)
  770.     {
  771.       tell (-1,msgfrom,"(sys)","You cannot become room coordinator.");
  772.       return;
  773.     }
  774.     if (job[0].fd!=0)
  775.     {
  776.       tell (-1,msgfrom,"(sys)","There is already a room coordinator.");
  777.       return;
  778.     }
  779.     sprintf (outtext,"New room coordinator: 0-%s",job[msgfrom].name);
  780.     tell (msgfrom,-1,"(sys)",outtext);
  781.     job[0].buf[0]=0;
  782.     strcpy(job[0].name,job[msgfrom].name);
  783.     strcpy(job[0].pass,job[msgfrom].pass);
  784.     strcpy(job[0].extra,job[msgfrom].extra);
  785.     strcpy(job[0].from,job[msgfrom].from);
  786.     job[0].fd=job[msgfrom].fd;
  787.     job[0].mode=job[msgfrom].mode;
  788.     job[0].gagged=job[msgfrom].gagged;
  789.     job[0].privconf=job[msgfrom].privconf;
  790.     job[0].maybeleader=job[msgfrom].maybeleader;
  791.     job[0].showcount=job[msgfrom].showcount;
  792.     job[0].showjob=job[msgfrom].showjob;
  793.     job[0].padname=job[msgfrom].padname;
  794.     job[0].userbt0=job[msgfrom].userbt0;
  795.     job[0].userbt1=job[msgfrom].userbt1;
  796.     job[0].userbt2=job[msgfrom].userbt2;
  797.     job[0].userbt3=job[msgfrom].userbt3;
  798.     job[0].userby0=job[msgfrom].userby0;
  799.     job[0].userby1=job[msgfrom].userby1;
  800.     job[0].userby2=job[msgfrom].userby2;
  801.     job[0].userby3=job[msgfrom].userby3;
  802.     job[0].userby4=job[msgfrom].userby4;
  803.     job[0].userby5=job[msgfrom].userby5;
  804.     job[0].userwd0=job[msgfrom].userwd0;
  805.     job[0].userwd1=job[msgfrom].userwd1;
  806.     strcpy (job[0].userstr,job[msgfrom].userstr);
  807. #ifdef TERMCAP
  808.     strcpy (job[0].termtype,job[msgfrom].termtype);
  809.     strcpy (job[0].al,job[msgfrom].al);
  810.     strcpy (job[0].bc,job[msgfrom].bc);
  811.     strcpy (job[0].cd,job[msgfrom].cd);
  812.     strcpy (job[0].ce,job[msgfrom].ce);
  813.     strcpy (job[0].cl,job[msgfrom].cl);
  814.     strcpy (job[0].dc,job[msgfrom].dc);
  815.     strcpy (job[0].dl,job[msgfrom].dl);
  816.     strcpy (job[0].so,job[msgfrom].so);
  817.     strcpy (job[0].se,job[msgfrom].se);
  818.     strcpy (job[0].sr,job[msgfrom].sr);
  819.     strcpy (job[0].cm,job[msgfrom].cm);
  820.     strcpy (job[0].cs,job[msgfrom].cs);
  821.     strcpy (job[0].rs,job[msgfrom].rs);
  822.     strcpy (job[0].xdo,job[msgfrom].xdo);
  823.     job[0].co=job[msgfrom].co;
  824.     job[0].li=job[msgfrom].li;
  825. #endif
  826.     job[msgfrom].fd=0;
  827.     job[msgfrom].mode=0;
  828.     job[msgfrom].name[0]=0;
  829.     job[msgfrom].pass[0]=0;
  830.     job[msgfrom].from[0]=0;
  831. #ifdef TERMCAP
  832.     job[msgfrom].termtype[0]=0;
  833. #endif
  834.     command[0]=0;
  835.     return;
  836.   }
  837.  
  838.   if (strcmp("*-",command)==0) /* Warning: whoever is RL is dropped */
  839.   {
  840.     if (job[msgfrom].maybeleader==0)
  841.     {
  842.       tell (-1,msgfrom,"(sys)","You can't get rid of the room leader.");
  843.       return;
  844.     }
  845.     if (job[0].fd==0)
  846.     {
  847.       tell (-1,msgfrom,"(sys)","There is no room leader to get rid of.");
  848.       return;
  849.     }
  850.     for (i=0;i<NUMJOBS;i++)
  851.     {
  852.       if (job[i].fd==0)
  853.     goto FOUNDSLOT; /* Yeah, I know, GOTOs are bad... */
  854.     }
  855.     tell (-1,msgfrom,"(sys)","There are no available user slots");
  856.     return;
  857. FOUNDSLOT:
  858.     sprintf (outtext,"0-%s is no longer room coordinator",job[0].name);
  859.     tell (msgfrom,-1,"(sys)",outtext);
  860.     job[i].buf[0]=0;
  861.     strcpy(job[i].name,job[0].name);
  862.     strcpy(job[i].pass,job[0].pass);
  863.     strcpy(job[i].from,job[0].from);
  864.     strcpy(job[i].extra,job[0].extra);
  865.     job[i].fd=job[0].fd;
  866.     job[i].mode=job[0].mode;
  867.     job[i].gagged=job[0].gagged;
  868.     job[i].privconf=job[0].privconf;
  869.     job[i].maybeleader=job[0].maybeleader;
  870.     job[i].showcount=job[0].showcount;
  871.     job[i].showjob=job[0].showjob;
  872.     job[i].padname=job[0].padname;
  873.     job[i].userbt0=job[0].userbt0;
  874.     job[i].userbt1=job[0].userbt1;
  875.     job[i].userbt2=job[0].userbt2;
  876.     job[i].userbt3=job[0].userbt3;
  877.     job[i].userby0=job[0].userby0;
  878.     job[i].userby1=job[0].userby1;
  879.     job[i].userby2=job[0].userby2;
  880.     job[i].userby3=job[0].userby3;
  881.     job[i].userby4=job[0].userby4;
  882.     job[i].userby5=job[0].userby5;
  883.     job[i].userwd0=job[0].userwd0;
  884.     job[i].userwd1=job[0].userwd1;
  885.     strcpy (job[i].userstr,job[0].userstr);
  886. #ifdef TERMCAP
  887.     strcpy (job[i].termtype,job[0].termtype);
  888.     strcpy (job[i].al,job[0].al);
  889.     strcpy (job[i].bc,job[0].bc);
  890.     strcpy (job[i].cd,job[0].cd);
  891.     strcpy (job[i].ce,job[0].ce);
  892.     strcpy (job[i].cl,job[0].cl);
  893.     strcpy (job[i].dc,job[0].dc);
  894.     strcpy (job[i].dl,job[0].dl);
  895.     strcpy (job[i].so,job[0].so);
  896.     strcpy (job[i].se,job[0].se);
  897.     strcpy (job[i].sr,job[0].sr);
  898.     strcpy (job[i].cm,job[0].cm);
  899.     strcpy (job[i].cs,job[0].cs);
  900.     strcpy (job[i].rs,job[0].rs);
  901.     strcpy (job[i].xdo,job[0].xdo);
  902.     job[i].co=job[0].co;
  903.     job[i].li=job[0].li;
  904. #endif
  905.     job[0].fd=0;
  906.     job[0].mode=0;
  907.     job[0].name[0]=0;
  908.     job[0].pass[0]=0;
  909.     job[0].from[0]=0;
  910. #ifdef TERMCAP
  911.     job[0].termtype[0]=0;
  912. #endif
  913.     command[0]=0;
  914.     endsession(0); /* Clear out all of the coord stuff. */
  915.     return;
  916.   }
  917.  
  918.   if (!per_process(msgfrom,command))
  919.     return;
  920.  
  921.   if (command[0]=='~')
  922.   {
  923.     tell (msgfrom,-2,"",command+1);
  924.     return;
  925.   }
  926.   if (command[0]=='*')
  927.   {
  928.     starcommand (msgfrom, command+1);
  929.     return;
  930.   }
  931.   if (command[0]=='/')
  932.   {
  933.     slashcommand (msgfrom, command+1);
  934.     return;
  935.   }
  936.   else
  937.   {
  938.     tell (msgfrom,-1,"",command);
  939.   }
  940. }
  941.  
  942. void relogin (msgfrom, command)
  943. int msgfrom;
  944. char *command;
  945. {
  946.   char *textptr;
  947.  
  948.   fprintf (masterfp,"(sys) RELOGIN: %d-%s\n",msgfrom,job[msgfrom].name);
  949.   if ((textptr=strtok(command," "))==NULL)
  950.   {
  951.     tell (-1,msgfrom,"","Enter your name:");
  952.     job[msgfrom].mode=1;
  953.     return;
  954.   }
  955.   strncpy (job[msgfrom].name,textptr,20);
  956.   job[msgfrom].mode=2;
  957.   loginuser(msgfrom);
  958.   return;
  959. }
  960.  
  961. void loginuser(id)
  962. int id;
  963. {
  964.   FILE *fp;
  965.   char string[128];
  966.   char name[20];
  967.   char pass[16];
  968.   char *textptr;
  969.   int i;
  970.  
  971.   if (!validjob(id))
  972.     return;
  973.  
  974.   if ((fp=fopen("mcm-accts","r"))==NULL)
  975.   {
  976.     strcpy(job[id].name,name);
  977.     job[id].from[0]=0;
  978.     job[id].maybeleader=0;
  979.     job[id].gagged=defaultgag;
  980.     job[id].privconf=0;
  981.     job[id].mode=3;
  982. #ifdef DFCOUNTS
  983.     job[id].showcount=TRUE;
  984. #else
  985.     job[id].showcount=FALSE;
  986. #endif
  987. #ifdef DFJOBNUMS
  988.     job[id].showjob=TRUE;
  989. #else
  990.     job[id].showjob=FALSE;
  991. #endif
  992. #ifdef DFNAMEPAD
  993.     job[id].padname=TRUE;
  994. #else
  995.     job[id].padname=FALSE;
  996. #endif
  997.     job[id].userbt0=0;
  998.     job[id].userbt1=0;
  999.     job[id].userbt2=0;
  1000.     job[id].userbt3=0;
  1001.     job[id].userby0=0;
  1002.     job[id].userby1=0;
  1003.     job[id].userby2=0;
  1004.     job[id].userby3=0;
  1005.     job[id].userby4=0;
  1006.     job[id].userby5=0;
  1007.     job[id].userwd0=0;
  1008.     job[id].userwd1=0;
  1009.     job[id].userstr[0]=0;
  1010.     tell (id,-1,"(sys)","User logging on");
  1011.     per_login(id);
  1012.     return; /* Let anyone in */
  1013.   }
  1014.   fgets (string,128,fp);
  1015.   while (!feof(fp))
  1016.   {
  1017.     if (string[0]=='#')
  1018.       goto COMMENTLOGIN; /* Yeah, I know I shouldn't GOTO */
  1019.     if ((textptr=strtok(string,":\n"))==NULL)
  1020.       textptr="*";
  1021.     strcpy (string,textptr);
  1022.     if ((textptr=strtok(NULL,":\n"))==NULL)
  1023.       textptr="*";
  1024.     strcpy (pass,textptr);
  1025.     if ((textptr=strtok(NULL,":\n"))==NULL)
  1026.       textptr="*";
  1027.     strcpy (job[id].from,textptr);
  1028.     if ((textptr=strtok(NULL,":\n"))==NULL)
  1029.       textptr="*";
  1030.     strcpy (job[id].extra,textptr);
  1031.     if (string[0]=='/')
  1032.     {
  1033.       strcpy (name,string+1);
  1034.       job[id].maybeleader=TRUE;
  1035.     }
  1036.     else
  1037.     {
  1038.       strcpy (name,string);
  1039.       job[id].maybeleader=FALSE;
  1040.     }
  1041.     strcap (name);
  1042.     strcap (job[id].name);
  1043.     strcap (pass);
  1044.     strcap (job[id].pass);
  1045.     if (strlen(job[id].name)==0)
  1046.     {
  1047.       goto NAMEPLEASE; /* Sorry */
  1048.     }
  1049.     if ((strncmp(name,job[id].name,20)==0)||(strcmp(name,"*")==0))
  1050.     {
  1051.       fclose (fp);
  1052.       if ((job[id].mode==1)&&(pass[0]!='*'))
  1053.       {
  1054.     job[id].mode=2;
  1055.     tell (-1,id,"","Restricted username; enter password:");
  1056.     return;
  1057.       }
  1058.       if ((job[id].mode==2)&&(pass[0]!='*'))
  1059.       {
  1060.     if (strncmp(pass,job[id].pass,16)!=0)
  1061.     {
  1062.       fprintf (masterfp,"(sys) BADPASS: %s\n",job[id].name);
  1063.       tell (-1,id,"","Invalid password entered.");
  1064. NAMEPLEASE:
  1065.       tell (-1,id,"","Enter your name:");
  1066.       job[id].mode=1;
  1067.       return;
  1068.     }
  1069.       }
  1070.       job[id].gagged=defaultgag;
  1071.       job[id].privconf=0;
  1072.       job[id].mode=3;
  1073.       job[id].showcount=TRUE;
  1074.       job[id].showjob=TRUE;
  1075.       job[id].padname=FALSE;
  1076.       job[id].userbt0=0;
  1077.       job[id].userbt1=0;
  1078.       job[id].userbt2=0;
  1079.       job[id].userbt3=0;
  1080.       job[id].userby0=0;
  1081.       job[id].userby1=0;
  1082.       job[id].userby2=0;
  1083.       job[id].userby3=0;
  1084.       job[id].userby4=0;
  1085.       job[id].userby5=0;
  1086.       job[id].userwd0=0;
  1087.       job[id].userwd1=0;
  1088.       job[id].userstr[0]=0;
  1089.       tell (id,-1,"(sys)","User logging in.");
  1090.       usertype (id,"mcm-hello");
  1091.       per_login(id);
  1092.       if (msgtext[0]!=0)
  1093.       {
  1094.     tell (-1,id,"(note)","There is a message on the door:");
  1095.     tell (-1,id,"",msgtext);
  1096.       }
  1097.       sprintf (string,"msg-%s",job[id].name);
  1098.       struncap(string);
  1099.       if (!access(string,R_OK))
  1100.       {
  1101.     tell (-1,id,"(msg)","There is a message waiting for you from the sysadmin:");
  1102.     usertype (id,string);
  1103.     tell (-1,id,"(msg)","Use the command /D to delete the note.");
  1104.       }
  1105.       return;
  1106.     }
  1107. COMMENTLOGIN:
  1108.     fgets (string,128,fp);
  1109.   }
  1110.   strcpy (string,"Login incorrect.  Try again.\r\nEnter your name:");
  1111.   tell (-1, id, "", string);
  1112.   job[id].mode=1;
  1113.   fclose (fp);
  1114.   return;
  1115. }
  1116.  
  1117. void strcap(string)
  1118. char *string;
  1119. {
  1120.   int i;
  1121.  
  1122.   for (i=0;i<strlen(string);i++)
  1123.     string[i]=toupper(string[i]);
  1124. }
  1125. void struncap(string)
  1126. char *string;
  1127. {
  1128.   int i;
  1129.  
  1130.   for (i=0;i<strlen(string);i++)
  1131.     string[i]=tolower(string[i]);
  1132. }
  1133.  
  1134. void starcommand(msgfrom, command)
  1135. int msgfrom;
  1136. char *command;
  1137. {
  1138.   int i,j;
  1139.   char string[256];
  1140.   char *textptr;
  1141.  
  1142.   if ((msgfrom!=0)&&(asstleader!=msgfrom))
  1143.   {
  1144.     tell (-1,msgfrom,"(sys)",
  1145.       "Must be the room coordinator to use * commands");
  1146.     return;
  1147.   }
  1148.   if (strncmp("E!",command,2)==0)
  1149.     bailout(0,"Coordinator shutdown");
  1150.   command[0]=toupper(command[0]);
  1151.   if ((msgfrom!=0)&&(strchr("DGTOLKM",command[0])==NULL))
  1152.   {
  1153.     command[0]='?';
  1154.   }
  1155.   switch (command[0])
  1156.   {
  1157.   case 'M':
  1158.     modecommand(msgfrom,command+1);
  1159.     return;
  1160.   case 'D':
  1161.     doormessage(msgfrom,command+1);
  1162.     return;
  1163.   case 'G':
  1164.     gagpeople(msgfrom,command+1);
  1165.     return;
  1166.   case 'C':
  1167.     privconf(msgfrom,command+1);
  1168.     return;
  1169.   case 'T':
  1170.     struncap (command);
  1171.     typefile (msgfrom,command+1);
  1172.     return;
  1173.   case 'O':
  1174.     tell (msgfrom,-1,"(sys)","Floor is now open for discussion");
  1175.     listen_mode= -1;
  1176.     return;
  1177.   case 'L':
  1178.     listenonly(msgfrom,command+1);
  1179.     return;
  1180.   case 'K':
  1181.     i=atoi(command+1);
  1182. /*    shutdown (job[i].fd,2);/**/
  1183.     endsession (i);
  1184.     return;
  1185.   case 'A':
  1186.     setasst(command+1);
  1187.     return;
  1188.   default:
  1189.     tell (-1,msgfrom,"","Valid * commands are: (* = avail to asst coord)");
  1190.     if (!per_starhelp(msgfrom))
  1191.       return;
  1192.     tell (-1,msgfrom,"","*D (text)    Put a 1 line message on the door*");
  1193.     tell (-1,msgfrom,"","*E!          End session; Shut down server*");
  1194.     tell (-1,msgfrom,"","*E-          Quit being room coordinator");
  1195.     tell (-1,msgfrom,"","*K (uid)     Kill a user*");
  1196.     tell (-1,msgfrom,"","*T (file)    Type file*");
  1197.     tell (-1,msgfrom,"","*G+(uid)     Gag user (uid) (*=all users)*");
  1198.     tell (-1,msgfrom,"","*G-(uid)     Ungag user (uid) (*=all users)*");
  1199.     tell (-1,msgfrom,"","*L (uid)     Put room in listen-only.  Give optional (uid) the floor*");
  1200.     tell (-1,msgfrom,"","*O           Open the floor for general discussion*");
  1201.     tell (-1,msgfrom,"","*C           Clear Private conference");
  1202.     tell (-1,msgfrom,"","*C(uid_list) Bring selected users into private conference");
  1203.     tell (-1,msgfrom,"","*A(uid)      Set the ass't coord (0=no ass't)");
  1204.     tell (-1,msgfrom,"","*M(mode)     Set system modes (*M? for more help)*");
  1205.     return;
  1206.   }
  1207. }      
  1208.  
  1209. void modecommand(msgfrom, command)
  1210. int msgfrom;
  1211. char *command;
  1212. {
  1213.   char string[80];
  1214.   if (msgfrom!=0)
  1215.     command[0]='?';
  1216.  
  1217.   if (!per_mode(msgfrom,command))
  1218.     return;
  1219.   switch (toupper(command[0]))
  1220.   {
  1221.   case 'S':
  1222.     if (command[1]=='+')
  1223.     {
  1224.       snoopmode=TRUE;
  1225.       tell (-1,msgfrom,"(sys)","Snoop mode on");
  1226.       return;
  1227.     }
  1228.     if (command[1]=='-')
  1229.     {
  1230.       snoopmode=FALSE;
  1231.       tell (-1,msgfrom,"(sys)","Snoop mode off");
  1232.       return;
  1233.     }
  1234.   case 'D':
  1235.     if (command[1]=='+')
  1236.     {
  1237.       defaultgag=TRUE;
  1238.       tell (-1,msgfrom,"(sys)","Default gag mode on");
  1239.       return;
  1240.     }
  1241.     if (command[1]=='-')
  1242.     {
  1243.       defaultgag=FALSE;
  1244.       tell (-1,msgfrom,"(sys)","Default gag mode off");
  1245.       return;
  1246.     }
  1247.   case 'H':
  1248.     if (command[1]=='+')
  1249.     {
  1250.       confhear=TRUE;
  1251.       tell (-1,msgfrom,"(sys)","Conference hearing mode on");
  1252.       return;
  1253.     }
  1254.     if (command[1]=='-')
  1255.     {
  1256.       confhear=FALSE;
  1257.       tell (-1,msgfrom,"(sys)","Conference hearing off");
  1258.       return;
  1259.     }
  1260.   case 'T':
  1261.     if (command[1]=='+')
  1262.     {
  1263.       conftalk=TRUE;
  1264.       tell (-1,msgfrom,"(sys)","Conference talk mode on");
  1265.       return;
  1266.     }
  1267.     if (command[1]=='-')
  1268.     {
  1269.       conftalk=FALSE;
  1270.       tell (-1,msgfrom,"(sys)","Conference talk mode off");
  1271.       return;
  1272.     }
  1273.   default:
  1274.     if (!per_modehelp(msgfrom))
  1275.       return;
  1276.     tell (-1,msgfrom,"(info)","The following modes are available:");
  1277.     sprintf (string,"*MD(+/-)    Set default gag mode (%c)",defaultgag?'+':'-');
  1278.     tell (-1,msgfrom,"",string);
  1279.     sprintf (string,"*MT(+/-)    Set conf. talk mode (%c)",conftalk?'+':'-');
  1280.     tell (-1,msgfrom,"",string);
  1281.     sprintf (string,"*MH(+/-)    Set conf. hear mode (%c)",confhear?'+':'-');
  1282.     tell (-1,msgfrom,"",string);
  1283.     sprintf (string,"*MS(+/-)    Set snoop mode (%c)",snoopmode?'+':'-');
  1284.     tell (-1,msgfrom,"",string);
  1285.     return;
  1286.   }
  1287. }
  1288.  
  1289. void setasst(command)
  1290. char *command;
  1291. {
  1292.   char string[132];
  1293.  
  1294.   asstleader=atoi(command);
  1295.   if (!testjob(asstleader))
  1296.     asstleader=0;
  1297.   if (asstleader!=0)
  1298.   {
  1299.     sprintf (string,"New ass't coordinator: %d-%s",asstleader,
  1300.          job[asstleader].name);
  1301.     tell (0,-1,"(sys)",string);
  1302.   }
  1303.   else
  1304.     tell (0,-1,"(sys)","There is no longer an ass't coordinator");
  1305.   return;
  1306. }
  1307.  
  1308. void slashcommand(msgfrom, command)
  1309. int msgfrom;
  1310. char *command;
  1311. {
  1312.   int i;
  1313.   char string[256];
  1314.   char *textptr;
  1315.  
  1316.   if (!testjob(msgfrom))
  1317.     return;
  1318.  
  1319.   command[0]=toupper(command[0]);
  1320.   switch (command[0])
  1321.   {
  1322.   case 'W':
  1323.   case 'U':
  1324.     whothere(msgfrom,command);
  1325.     return;
  1326.   case 'E':
  1327.   case 'X':
  1328.   case 'Q':
  1329. /*    shutdown (job[msgfrom].fd,2);/**/
  1330.     endsession (msgfrom);
  1331.     return;
  1332.   case 'D':
  1333.     sprintf (string,"msg-%s",job[msgfrom].name);
  1334.     struncap(string);
  1335.     unlink(string);
  1336.     tell (-1,msgfrom,"(sys)","Any pending messages deleted.");
  1337.     return;
  1338.   case 'R':
  1339.     rolldice (msgfrom,command+1,1);
  1340.     return;
  1341.   case 'P':
  1342.     rolldice (msgfrom,command+1,0);
  1343.     return;
  1344.   case 'H':
  1345.     struncap (command);
  1346.     userhelp (msgfrom,command+1);
  1347.     return;
  1348.   case 'L':
  1349.     relogin (msgfrom,command+1);
  1350.     return;
  1351.   case 'S':
  1352.     sendmsg (msgfrom,command+1);
  1353.     return;
  1354.   case 'V':
  1355.     tell (-1,msgfrom,"(sys)",VERSION);
  1356.     return;
  1357. #ifdef TERMCAP
  1358.   case 'T':
  1359.     struncap (command);
  1360.     dowins (msgfrom,command+1);
  1361.     return;
  1362.   case '#':
  1363.     set_lines(msgfrom,atoi(command+1));
  1364.     return;
  1365. #endif
  1366.   case 'C':
  1367.     set_count(msgfrom,command+1);
  1368.     return;
  1369.   case 'J':
  1370.     set_jobid(msgfrom,command+1);
  1371.     return;
  1372.   case 'N':
  1373.     set_namepad(msgfrom,command+1);
  1374.     return;
  1375.   default:
  1376.     tell (-1,msgfrom,"","Valid / commands are:");
  1377.     if (!per_slashhelp(msgfrom))
  1378.       return;
  1379.     tell (-1,msgfrom,"","/C [+/-]          Set/Clear display of message counter");
  1380.     tell (-1,msgfrom,"","/E              Exit this system");
  1381.     tell (-1,msgfrom,"","/H              Additional help text");
  1382.     tell (-1,msgfrom,"","/J [+/-]     Set/Clear display of job ids");
  1383.     tell (-1,msgfrom,"","/L [name]       Re-login under different name");
  1384.     tell (-1,msgfrom,"","/N [+/-]     Set/Clear name padding");
  1385.     tell (-1,msgfrom,"","/P [dice]       Privately roll dice");
  1386.     tell (-1,msgfrom,"","/R [dice]       Roll dice  (example: /R 1d6+2)");
  1387.     tell (-1,msgfrom,"","/S (job) (msg)  Send private message to user");
  1388. #ifdef TERMCAP
  1389.     tell (-1,msgfrom,"","/T (term_type)  Invoke split-screen mode");
  1390. #endif
  1391.     tell (-1,msgfrom,"","/U            Brief list of users online");
  1392.     tell (-1,msgfrom,"","/V              Get version ID of server");
  1393.     tell (-1,msgfrom,"","/W              List who is online");
  1394. #ifdef TERMCAP
  1395.     tell (-1,msgfrom,"","/# (number)     Set lines per page (split screen mode");
  1396. #endif
  1397.   }
  1398. }
  1399.  
  1400. void listenonly(msgfrom, command)
  1401. int msgfrom;
  1402. char *command;
  1403. {
  1404.   char string[128];
  1405.  
  1406.   if (!testjob(msgfrom))
  1407.     return;
  1408.  
  1409.   if (listen_mode== -1)
  1410.     tell (msgfrom,-2,"(sys)","Floor is now in listen-only mode.");
  1411.   listen_mode=atoi(command);
  1412.   if (!testjob(listen_mode))
  1413.     listen_mode=0;
  1414.   sprintf (string,"User %d-%s now has the floor",listen_mode,
  1415.          job[listen_mode].name);
  1416.   tell (msgfrom,-2,"(sys)",string);
  1417. }
  1418.  
  1419. void set_count(msgfrom,command)
  1420. int msgfrom;
  1421. char *command;
  1422. {
  1423.   if (!testjob(msgfrom))
  1424.     return;
  1425.  
  1426.   if (command[0]=='+')
  1427.     job[msgfrom].showcount=TRUE;
  1428.   else if (command[0]=='-')
  1429.     job[msgfrom].showcount=FALSE;
  1430.   else
  1431.     job[msgfrom].showcount=job[msgfrom].showcount?FALSE:TRUE;
  1432.   if (job[msgfrom].showcount)
  1433.     tell (-1,msgfrom,"(sys)","Count display will now be shown");
  1434.   else
  1435.     tell (-1,msgfrom,"(sys)","Count display will no longer be shown");
  1436. }
  1437.  
  1438. void set_jobid(msgfrom,command)
  1439. int msgfrom;
  1440. char *command;
  1441. {
  1442.   if (!testjob(msgfrom))
  1443.     return;
  1444.  
  1445.   if (command[0]=='+')
  1446.     job[msgfrom].showjob=TRUE;
  1447.   else if (command[0]=='-')
  1448.     job[msgfrom].showjob=FALSE;
  1449.   else
  1450.     job[msgfrom].showjob=job[msgfrom].showjob?FALSE:TRUE;
  1451.   if (job[msgfrom].showcount)
  1452.     tell (-1,msgfrom,"(sys)","Job ID display will now be shown");
  1453.   else
  1454.     tell (-1,msgfrom,"(sys)","Job ID display will no longer be shown");
  1455. }
  1456.  
  1457. void set_namepad(msgfrom,command)
  1458. int msgfrom;
  1459. char *command;
  1460. {
  1461.   if (!testjob(msgfrom))
  1462.     return;
  1463.  
  1464.   if (command[0]=='+')
  1465.     job[msgfrom].padname=TRUE;
  1466.   else if (command[0]=='-')
  1467.     job[msgfrom].padname=FALSE;
  1468.   else
  1469.     job[msgfrom].padname=job[msgfrom].padname?FALSE:TRUE;
  1470.   if (job[msgfrom].padname)
  1471.     tell (-1,msgfrom,"(sys)","Name padding will now be done");
  1472.   else
  1473.     tell (-1,msgfrom,"(sys)","Name padding will no longer be done");
  1474. }
  1475.  
  1476. void sendmsg (msgfrom, command)
  1477. int msgfrom;
  1478. char *command;
  1479. {
  1480.   char *textptr;
  1481.   int i;
  1482.  
  1483.   if ((textptr=strtok(command," \n"))==NULL)
  1484.   {
  1485.     tell (msgfrom,-1,"(sys)","Syntax: /s (job) (message)");
  1486.     return;
  1487.   }
  1488.   i=atoi(textptr);
  1489.   textptr=strtok(NULL,"\n");
  1490.   if (!testjob(i))
  1491.   {
  1492.     tell (-1,msgfrom,"(sys)","Job is not online");
  1493.     return;
  1494.   }
  1495.   tell (-1,msgfrom,"(sys)","Sending private message");
  1496.   tell (msgfrom,i,"",textptr);
  1497.   return;
  1498. }
  1499.  
  1500. void doormessage (msgfrom,message)
  1501. int msgfrom;
  1502. char *message;
  1503. {
  1504.   int i;
  1505.  
  1506.   i=(msgfrom==0)?-1:msgfrom; /* Ha! Let the fortran people figure THIS out! */
  1507.   while (message[0]==' ')
  1508.   {
  1509.     message++;
  1510.   }
  1511.   if (message[0]==0)
  1512.   {
  1513.     fprintf (masterfp,"(sys) DOOR: Message cleared\n");
  1514.     msgtext[0]=0;
  1515.     tell (i,0,"(sys)","Message cleared from door");
  1516.     return;
  1517.   }
  1518.   strcpy (msgtext,message);
  1519.   fprintf (masterfp,"(sys) New message on door:\n%s\n",msgtext);
  1520.   tell (i,0,"(sys)","Message now on door");
  1521.   tell (i,0,"",msgtext);
  1522. }
  1523.  
  1524.  
  1525. #ifdef TERMCAP
  1526. void dowins (msgfrom,command)
  1527. int msgfrom;
  1528. char *command;
  1529. {
  1530.   char *textptr;
  1531.  
  1532.   textptr=strtok(command," \n");
  1533.   if ((job[msgfrom].termtype[0]==0)&&(textptr==NULL))
  1534.   {
  1535.     tell (-1,msgfrom,"(sys)","Usage: /t (termtype)");
  1536.     return;
  1537.   }
  1538.   if ((job[msgfrom].termtype[0]!=0)&&(textptr==NULL))
  1539.   {
  1540.     fprintf (masterfp,"(sys) DOWINS: %d-%s exit\n",msgfrom,job[msgfrom].name);
  1541.     splend (msgfrom);
  1542.     tell (-1,msgfrom,"(sys)","Exiting split screen.");
  1543.     return;
  1544.   }
  1545.   if (job[msgfrom].termtype[0]!=0)
  1546.   {
  1547.     splend (msgfrom);
  1548.   }
  1549.   struncap (textptr);
  1550.   fprintf (masterfp,"(sys) DOWINS: %d-%s [%s]\n",msgfrom,job[msgfrom].name,
  1551.        textptr);
  1552.   tell (-1,msgfrom,"(sys)","Entering split screen.");
  1553.   splinit(msgfrom,textptr);
  1554.   return;
  1555. }
  1556. #endif
  1557.  
  1558. void rolldice (msgfrom,command,pubroll)
  1559. int msgfrom;
  1560. char *command;
  1561. int pubroll;
  1562. {
  1563.   int i,j;
  1564.   double f;
  1565.  
  1566.   int rolls[50],total;
  1567.   int number,sides;
  1568.   int modifr;
  1569.   char string[132];
  1570.   char *textptr;
  1571.   char string2[32];
  1572.  
  1573.   for (i=0;i<50;i++)
  1574.     rolls[i]=0;
  1575.   if (!per_preroll(msgfrom,command))
  1576.     return;
  1577.   textptr=strtok(command," \n");
  1578.   if (textptr!=NULL)
  1579.   {
  1580.     if (isdigit(textptr[0]))
  1581.       number=atoi(textptr);
  1582.     else
  1583.       number=1;
  1584.     while ((textptr[0]!='D')&&(textptr[0]!='d')&&(textptr[0]!=0))
  1585.       textptr++;
  1586.     if (textptr[0]!=0)
  1587.     {
  1588.       textptr++;
  1589.       if (isdigit(textptr[0]))
  1590.     sides=atoi(textptr);
  1591.       else
  1592.     sides=6;
  1593.       while ((textptr[0]!='+')&&(textptr[0]!='-')&&(textptr[0]!=0))
  1594.     textptr++;
  1595.       if ((textptr[0]=='+')||(textptr[0]=='-'))
  1596.     modifr=atoi(textptr);
  1597.       else
  1598.     modifr=0;
  1599.     }
  1600.     else
  1601.     {
  1602.       sides=6;
  1603.       modifr=0;
  1604.     }
  1605.   }
  1606.   else
  1607.   {
  1608.     number=1;
  1609.     sides=6;
  1610.     modifr=0;
  1611.   }
  1612.   total=0;
  1613.   if (sides>1000)
  1614.     sides=1000;
  1615.   if (number>50)
  1616.     number=50;
  1617.   for (i=0;i<number;i++)
  1618.   {
  1619.     j=lrand48()%sides;
  1620.     j++;
  1621.     rolls[i]=j;
  1622.     total+=j;
  1623.   }
  1624.   total += modifr;
  1625.   if (modifr==0)
  1626.     sprintf (string,"%dd%d -> %d ",number,sides,total);
  1627.   else
  1628.     sprintf (string,"%dd%d%+d -> %d ",number,sides,modifr,total);
  1629.   if (number<=20)
  1630.   {
  1631.     for (i=0;i<number;i++)
  1632.     {
  1633.       if (i==0)
  1634.     sprintf (string2,"(%d",rolls[i]);
  1635.       else
  1636.     sprintf (string2,",%d",rolls[i]);
  1637.       strcat (string,string2);
  1638.     }
  1639.     strcat (string,")");
  1640.   }
  1641.   if (!per_postroll(pubroll,job,string,total,number,sides,rolls))
  1642.     return;
  1643.   if (pubroll==1)
  1644.     tell (msgfrom,-3,"(roll)",string);
  1645.   else
  1646.   {
  1647.     tell (msgfrom,msgfrom,"(roll)",string);
  1648.     if ((msgfrom!=0)&&(job[0].mode==3))
  1649.       tell (msgfrom,0,"(roll)",string);
  1650.   }
  1651.   return;
  1652. }
  1653.  
  1654.   
  1655. void endsession(msgfrom)
  1656. int msgfrom;
  1657. {
  1658.   int i;
  1659.   per_logout(msgfrom);
  1660.   if (msgfrom==asstleader)
  1661.     asstleader=0;
  1662.   if (msgfrom==0)
  1663.   {
  1664.     asstleader=0;
  1665.     snoopmode=FALSE;
  1666.     listen_mode= -1;
  1667.     defaultgag=FALSE;
  1668.     for (i=1;i<NUMJOBS;i++)
  1669.     {
  1670.       if (validjob(i))
  1671.       {
  1672.     job[i].gagged=FALSE;
  1673.     job[i].privconf=FALSE;
  1674.       }
  1675.     }
  1676.   }
  1677.  
  1678.   if (!validjob(msgfrom))
  1679.   {
  1680.     return;
  1681.   }
  1682.  
  1683.   if (job[msgfrom].fd==0)
  1684.     return;
  1685.  
  1686. #ifdef TERMCAP
  1687.   if (job[msgfrom].termtype[0]!=0)
  1688.     splend(msgfrom);
  1689. #endif
  1690.  
  1691.   if (job[msgfrom].mode==3)
  1692.   {
  1693.     tell (msgfrom,-1,"(sys)","User logging off");
  1694.     write (job[msgfrom].fd,"Goodbye.\r\n",10);
  1695.   }
  1696.   job[msgfrom].mode=0;
  1697.   job[msgfrom].name[0]=0;
  1698. /*  shutdown (job[msgfrom].fd,2);*/
  1699.   close (job[msgfrom].fd);
  1700.   job[msgfrom].fd=0;
  1701. }
  1702.  
  1703. void whothere(msgfrom,command)
  1704. int msgfrom;
  1705. char *command;
  1706. {
  1707.   int i,j;
  1708.   char string[80];
  1709.   char substring[40];
  1710.  
  1711.   if (toupper(command[0]=='U'))
  1712.   {
  1713.     tell (-1,msgfrom,"(info)","Users currently logged into the system");
  1714.     j=0;
  1715.     for (i=0;i<NUMJOBS;i++)
  1716.     {
  1717.       if (testjob(i))
  1718.       {
  1719.     sprintf (substring,"%s%s%d-%-20s  ",
  1720.            job[i].gagged?"G":" ",
  1721.            job[i].privconf?"C":" ", i,
  1722.            job[i].name);
  1723.     if (j==0)
  1724.     {
  1725.       strcpy (string,substring);
  1726.       j=1;
  1727.     }
  1728.     else
  1729.     {
  1730.       strcat (string,substring);
  1731.       tell (-1,msgfrom,"",string);
  1732.       j=0;
  1733.     }
  1734.       }
  1735.     }
  1736.     if (j==1)
  1737.       tell (-1,msgfrom,"",string);
  1738.     return;
  1739.   }
  1740.   if ((listen_mode>=0)&&(testjob(listen_mode)))
  1741.   {
  1742.     sprintf (string,"Floor is listen only; %d-%s has floor",listen_mode,
  1743.          job[listen_mode].name);
  1744.     tell (-1,msgfrom,"(info)",string);
  1745.   }
  1746.   if (job[msgfrom].gagged==1)
  1747.     tell (-1,msgfrom,"(info)","You are gagged");
  1748.   if (asstleader!=0)
  1749.   {
  1750.     sprintf (string,"Assistant room coordinator: %d-%s",asstleader,
  1751.          job[asstleader].name);
  1752.     tell (-1,msgfrom,"(info)",string);
  1753.   }
  1754.   tell (-1,msgfrom,"(info)","Users currently logged into the system");
  1755.   for (i=0;i<NUMJOBS;i++)
  1756.   {
  1757.     if (testjob(i))
  1758.     {
  1759.       if ((job[i].extra[0]!=0)&&((job[i].extra[0]!='*')||(msgfrom==0)))
  1760.     strcpy (substring,job[i].extra);
  1761.       else
  1762.     substring[0]=0;
  1763.       sprintf (string,"%s%s%d-%-20s %-32s",
  1764.            job[i].gagged?"(G)":"   ",
  1765.            job[i].privconf?"(C)":"   ", i,
  1766.            job[i].name, substring);
  1767.       tell (-1,msgfrom,"",string);
  1768.       if ((job[i].from[0]!=0)&&((job[i].from[0]!='*')||(msgfrom==0)))
  1769.       {
  1770.     sprintf (string,"              E-Mail address: %s",job[i].from);
  1771.     tell (-1,msgfrom,"",string);
  1772.       }
  1773.     }
  1774.   }
  1775. }
  1776.  
  1777. void gagpeople(msgfrom,command)
  1778. int msgfrom;
  1779. char *command;
  1780. {
  1781.   int i,j, sender;
  1782.   char string[80];
  1783.  
  1784.   sender=(msgfrom==0?-1:msgfrom);
  1785.   if (!testjob(msgfrom))
  1786.     return;
  1787.  
  1788.   if (command[0]=='D')
  1789.   {
  1790.     if (command[1]=='+')
  1791.     {
  1792.       defaultgag=1;
  1793.       tell (sender,0,"(sys)","New users will now be gagged");
  1794.       return;
  1795.     }
  1796.     if (command[1]=='-')
  1797.     {
  1798.       defaultgag=0;
  1799.       tell (sender,0,"(sys)","New users will now be ungagged");
  1800.       return;
  1801.     }
  1802.     return;
  1803.   }
  1804.   else if (command[0]=='+')
  1805.   {
  1806.     if (command[1]=='*')
  1807.     {
  1808.       for (i=1;i<NUMJOBS;i++)
  1809.     job[i].gagged=1;
  1810.       tell (msgfrom,-1,"(sys)","All users are now gagged.");
  1811.       return;
  1812.     }
  1813.     i=atoi(command+1);
  1814.     if (!testjob(i))
  1815.     {
  1816.       tell (-1,msgfrom,"(sys)","No such user");
  1817.       return;
  1818.     }
  1819.     job[i].gagged=1;
  1820.     sprintf (string,"You are gagged, all messages will go to 0-%s",
  1821.          job[0].name);
  1822.     tell (msgfrom,i,"(sys)",string);
  1823.     sprintf (string,"User %d-%s is now gagged",i,job[i].name);
  1824.     tell (-1,0,"(sys)",string);
  1825.     return;
  1826.   }
  1827.   else if (command[0]=='-')
  1828.   {
  1829.     if (command[1]=='*')
  1830.     {
  1831.       for (i=0;i<NUMJOBS;i++)
  1832.     job[i].gagged=0;
  1833.       tell (msgfrom,-1,"(sys)","All users are now ungagged.");
  1834.       return;
  1835.     }
  1836.     i=atoi(command+1);
  1837.     if (!testjob(i))
  1838.     {
  1839.       tell (-1,msgfrom,"(sys)","No such user");
  1840.       return;
  1841.     }
  1842.     job[i].gagged=0;
  1843.     tell (msgfrom,i,"(sys)","You are no longer gagged.");
  1844.     sprintf (string,"User %d-%s is now ungagged",
  1845.          i,job[i].name);
  1846.     tell (-1,0,"(sys)",string);
  1847.     return;
  1848.   }
  1849. }
  1850.  
  1851. void privconf(msgfrom,command)
  1852. int msgfrom;
  1853. char* command;
  1854. {
  1855.   int i;
  1856.   char string[80];
  1857.   char *textptr;
  1858.  
  1859.   tell (msgfrom,-2,"(sys)","Clearing private conference room.");
  1860.   tell (-1,msgfrom,"(sys)","Use ~text to send messages to people out of conf.");
  1861.   for (i=0;i<NUMJOBS;i++)
  1862.     job[i].privconf=0;
  1863.   textptr=strtok(command," ");
  1864.   while (textptr!=NULL)
  1865.   {
  1866.     job[0].privconf=1;
  1867.     i=atoi(textptr);
  1868.     if (testjob(i))
  1869.     {
  1870.       job[i].privconf=1;
  1871.       sprintf (string,"User %d-%s in private conference with 0-%s.",
  1872.          i,job[i].name,job[0].name);
  1873.       tell (msgfrom,-2,"(sys)",string);
  1874.     }
  1875.     textptr=strtok(NULL," ");
  1876.   }
  1877.   return;
  1878. }
  1879.  
  1880. void typefile(msgfrom,command)
  1881. int msgfrom;
  1882. char *command;
  1883. {
  1884.   FILE *fp;
  1885.   int linect;
  1886.   char fname[300];
  1887.   int shortct;
  1888.   int i;
  1889.   char string[256];
  1890.   char *textptr;
  1891.  
  1892.   if (strchr(command,'/')!=NULL)
  1893.   {
  1894.     tell (-1,msgfrom,"(sys)","Character / not allowed in filename");
  1895.     return;
  1896.   }
  1897.   textptr=strtok(command," ");
  1898.   sprintf (fname,"mcm.%s",textptr);
  1899.   if ((fp=fopen(fname,"r"))==NULL)
  1900.   {
  1901.     sprintf (string,"File %s not found",fname);
  1902.     tell (-1,msgfrom,"(sys)",string);
  1903.     return;
  1904.   }
  1905.   tell (msgfrom,-1,"(file)","Start of file transmission...");
  1906.   linect=0;
  1907.   fgets (string,100,fp);
  1908.   while (!feof(fp))
  1909.   {
  1910.     linect++;
  1911.     shortct++;
  1912.     if (shortct>5)
  1913.     {
  1914.       communicate();
  1915.       shortct=0;
  1916.     }
  1917.     if (linect>30)
  1918.     {
  1919.       tell (msgfrom,-1,"(file)",
  1920.         "File continues beyond 30 lines; will not display.");
  1921.       tell (msgfrom,-1,"(file)","End of file transmission");
  1922.       fclose (fp);
  1923.       return;
  1924.     }
  1925.     if (strlen(string)!=0)
  1926.       string[strlen(string)-1]=0;
  1927.     if (job[msgfrom].privconf)
  1928.       tell (-1,-10,"",string);
  1929.     else
  1930.       tell (-1,-1,"",string);
  1931.     fgets (string,100,fp);
  1932.   }
  1933.   tell (msgfrom,-1,"(file)","End of file transmission");
  1934.   fclose (fp);
  1935.   return;
  1936. }
  1937.  
  1938. void usertype (id,fname)
  1939. int id;
  1940. char *fname;
  1941. {
  1942.   FILE *fp;
  1943.   char string[255];
  1944.  
  1945.   if ((fp=fopen(fname,"r"))==NULL)
  1946.   {
  1947.     sprintf (string,"File %s not found",fname);
  1948.     tell (-1,id,"(sys)",string);
  1949.     return;
  1950.   }
  1951.   fgets (string,255,fp);
  1952.   while (!feof(fp))
  1953.   {
  1954.     string[strlen(string)-1]=0;
  1955.     tell (-1,id,"",string);
  1956.     fgets (string,255,fp);
  1957.   }
  1958.   fclose (fp);
  1959. }
  1960.  
  1961. void userhelp(id,command)
  1962. int id;
  1963. char *command;
  1964. {
  1965.   char *textptr;
  1966.   char fname[255];
  1967.  
  1968.   if (strchr(command,'/')!=NULL)
  1969.   {
  1970.     tell (-1,id,"(sys)","Illegal help file name");
  1971.     return;
  1972.   }
  1973.   textptr=strtok(command," ");
  1974.   if (textptr==NULL)
  1975.     strcpy (fname,"mcm-help");
  1976.   else
  1977.     sprintf (fname,"mcm-help-%s",textptr);
  1978.   fprintf (masterfp,"(sys) HELP: %d-%s: %s\n",id,job[id].name,fname);
  1979.   usertype (id,fname);
  1980. }
  1981.